import { _decorator, Component, Node, input, Input, EventKeyboard, KeyCode, Vec2 } from 'cc';
import { inputConfig } from './input_config';
const { ccclass, property } = _decorator;

/**
 * 键盘输入
 */
@ccclass('Keyboard')
export class Keyboard {
    protected _inputKeys: Map<string, boolean>;
    protected _primaryMovment: Vec2 | null = null;
    protected _sceondaryMovment: Vec2 | null = null;

    protected _keyToInputMap: Map<number, string> = new Map();
    protected _primaryKey: number[] = []; // wsad
    protected _secondaryKey: number[] = []; // up down left right

    private _primary: number[] = new Array(4).fill(0)
    private _secondary: number[] = new Array(4).fill(0)

    constructor (primary: Vec2 | null, sceondary: Vec2 | null, inputKeys: Map<string, boolean>) {
        input.on(Input.EventType.KEY_DOWN, this._onKeyDown, this);
        input.on(Input.EventType.KEY_UP, this._onKeyUp, this);
        this._primaryMovment = primary;
        this._sceondaryMovment = sceondary;
        this._inputKeys = inputKeys;

        this.convertInputConfig();
    }

    /**
     * 释放
     */
    public destory () {
        this._primaryMovment = null;
        this._sceondaryMovment = null;
        this._inputKeys = new Map;
        input.off(Input.EventType.KEY_DOWN, this._onKeyDown, this);
        input.off(Input.EventType.KEY_UP, this._onKeyUp, this);
    }

    /**
    * 按键按下
    * @param event 
    */
    private _onKeyDown (event: EventKeyboard) {
        let index = this._primaryKey.indexOf(event.keyCode);
        if (index != -1 && this._primaryMovment) {
            this._primary[index] = 1;
            this._primaryMovment.set(this._primary[3] - this._primary[2], this._primary[0] - this._primary[1]);
        }

        index = this._secondaryKey.indexOf(event.keyCode);
        if (index != -1 && this._sceondaryMovment) {
            this._secondary[index] = 1;
            this._sceondaryMovment.set(this._secondary[3] - this._secondary[2], this._secondary[0] - this._secondary[1]);
        }

        if (this._keyToInputMap.get(event.keyCode)) {
            this._inputKeys.set(this._keyToInputMap.get(event.keyCode)!, true)
        } else {
            this._inputKeys.set("" + event.keyCode, true)
        }

    }

    /**
     * 按键弹起
     * @param event 
     */
    private _onKeyUp (event: EventKeyboard) {
        let index = this._primaryKey.indexOf(event.keyCode);
        if (index != -1 && this._primaryMovment) {
            this._primary[index] = 0;
            this._primaryMovment.set(this._primary[3] - this._primary[2], this._primary[0] - this._primary[1]);
        }

        index = this._secondaryKey.indexOf(event.keyCode);
        if (index != -1 && this._sceondaryMovment) {
            this._secondary[index] = 0;
            this._sceondaryMovment.set(this._secondary[3] - this._secondary[2], this._secondary[0] - this._secondary[1]);
        }

        if (this._keyToInputMap.get(event.keyCode)) {
            this._inputKeys.set(this._keyToInputMap.get(event.keyCode)!, false)
        } else {
            this._inputKeys.set("" + event.keyCode, false)
        }
    }

    /**
     * 转换输入按键配置表为keyCode
     */
    public convertInputConfig () {
        this._primaryKey.length = 0;
        this._primaryKey.push(this._inputKey2KeyCode(inputConfig.primary.Y[0]));
        this._primaryKey.push(this._inputKey2KeyCode(inputConfig.primary.Y[1]));
        this._primaryKey.push(this._inputKey2KeyCode(inputConfig.primary.X[0]));
        this._primaryKey.push(this._inputKey2KeyCode(inputConfig.primary.X[1]));

        this._secondaryKey.length = 0;
        this._secondaryKey.push(this._inputKey2KeyCode(inputConfig.secondary.Y[0]));
        this._secondaryKey.push(this._inputKey2KeyCode(inputConfig.secondary.Y[1]));
        this._secondaryKey.push(this._inputKey2KeyCode(inputConfig.secondary.X[0]));
        this._secondaryKey.push(this._inputKey2KeyCode(inputConfig.secondary.X[1]));

        inputConfig.controlKeys.forEach((inputKey, control) => {
            let keyCode = this._inputKey2KeyCode(inputKey);
            if (keyCode) {
                this._keyToInputMap.set(keyCode, control);
                this._inputKeys.set(control, false);
            }
        });
    }

    /**
     * 将配置表的输入按键转换为实际按键
     * @param key 
     * @returns 
     */
    private _inputKey2KeyCode (key: string) {
        key = key.toUpperCase();
        if (key.length == 1) {
            if (!isNaN(Number(key))) {
                //@ts-ignore
                return KeyCode[`NUM_${key}`]
            }
            //@ts-ignore
            return KeyCode[`KEY_${key}`]
        }
        else if (key == "LEFT" || key == "UP" || key == "RIGHT" || key == "DOWN") {
            return KeyCode[`ARROW_${key}`];
        }
        else {
            //@ts-ignore
            return KeyCode[key];
        }
    }
}

